#include "udpServer.hpp"
#include "userManager.hpp"
#include <memory>
#include <unordered_map>
#include <fstream>
#include <signal.h>

std::unordered_map<std::string, std::string> dict;
const std::string dict_path = "dict.txt";

void Usage(const char *proc)
{
    std::cout << "\nUsage:\n\t" << proc << " local_port\n"
              << std::endl;
}

bool CutString(const std::string &message, std::string *key, std::string *value, const std::string &sep)
{
    size_t pos = message.find(sep);
    if (pos == std::string::npos)
        return false;
    *key = message.substr(0, pos);
    *value = message.substr(pos + sep.size());
    return true;
}

void Init_Dict()
{
    std::ifstream in(dict_path);

    if (!in.is_open())
    {
        std::cerr << "Open err" << std::endl;
        exit(OPER_ERR);
    }
    std::string line;
    std::string key, value;
    while (getline(in, line))
    {
        if (CutString(line, &key, &value, ":"))
        {
            dict[key] = value;
        }
    }
}


//查字典服务
void Dict_Serve(int sockfd, const sockaddr_in &client, std::string key) // 通信与业务解耦
{
    std::string response;
    auto it = dict.find(key);
    if (it == dict.end())
        response = "字典里不存在";
    else
        response = it->second;

    sendto(sockfd, response.c_str(), response.size(), 0, (struct sockaddr *)&client, sizeof(client));
}

//命令行程序替换服务
void Exec_Serve(int sockfd, const sockaddr_in &client, std::string command)
{
    std::string response;
    FILE *fp = popen(command.c_str(), "r"); // 相当于fork, pipe, exec三合一
    if (fp == nullptr)
    {
        response = command + "exec failed";
    }
    else
    {
        char line[1024];
        while (fgets(line, sizeof(line), fp))
        {
            response += line;
        }
    }
    pclose(fp);

    sendto(sockfd, response.c_str(), response.size(), 0, (struct sockaddr *)&client, sizeof(client));

}


//聊天室转发消息服务
userManager usermanager;
void Broadcast_Serve(int sockfd, const sockaddr_in &client, std::string message)
{
    std::string clientip = inet_ntoa(client.sin_addr);
    uint16_t clientport = ntohs(client.sin_port);

    //输入上线添加进用户管理
    if(message == "online")usermanager.addUser(sockfd, clientip, clientport);
    //如果没上线，单独发给用让他上线
    if(!usermanager.is_Online(clientip, clientport))
    {
        message = "Please enter online";
        sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr*)&client, sizeof(client));
        return;
    }
    if(message == "offline")usermanager.delUser(clientip, clientport);

    std::string broadmessage = '[' + clientip + '-' + std::to_string(clientport) + "]#" + message;
    usermanager.broadcast(sockfd, broadmessage);
    
}

void handler(int signo)
{
    Init_Dict();
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }

    uint16_t localport = atoi(argv[1]);

    // Init_Dict();
    // signal(3, handler); // 热加载字典
    // std::unique_ptr<udpServer> usvr(new udpServer(localport, Dict_Serve));

    // std::unique_ptr<udpServer> usvr(new udpServer(localport, Exec_Serve));

    std::unique_ptr<udpServer> usvr(new udpServer(localport, Broadcast_Serve));
    

    usvr->initServer();
    usvr->start();
    return 0;
}